/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package com.s2aei.model.dao;

import com.s2aei.model.Administrador;
import com.s2aei.model.Aluno;
import com.s2aei.model.Avaliador;
import com.s2aei.model.Papeis;
import com.s2aei.model.Professor;
import com.s2aei.model.Status;
import com.s2aei.model.Usuario;
import com.s2aei.model.dao.exceptions.IllegalOrphanException;
import com.s2aei.model.dao.exceptions.NonexistentEntityException;
import com.s2aei.model.dao.exceptions.PreexistingEntityException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityNotFoundException;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

/**
 *
 * @author Christian
 */
public class UsuarioDao implements Serializable {

    public UsuarioDao() {
        this.emf = Persistence.createEntityManagerFactory("S2AEILibPU");
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Usuario usuario) throws PreexistingEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Professor professor = usuario.getProfessor();
            if (professor != null) {
                professor = em.getReference(professor.getClass(), professor.getProfessorId());
                usuario.setProfessor(professor);
            }
            Administrador administrador = usuario.getAdministrador();
            if (administrador != null) {
                administrador = em.getReference(administrador.getClass(), administrador.getAdminId());
                usuario.setAdministrador(administrador);
            }
            Status status = usuario.getStatus();
            if (status != null) {
                status = em.getReference(status.getClass(), status.getTipo());
                usuario.setStatus(status);
            }
            Papeis papel = usuario.getPapel();
            if (papel != null) {
                papel = em.getReference(papel.getClass(), papel.getTipo());
                usuario.setPapel(papel);
            }
            Avaliador avaliador = usuario.getAvaliador();
            if (avaliador != null) {
                avaliador = em.getReference(avaliador.getClass(), avaliador.getAvaliadorId());
                usuario.setAvaliador(avaliador);
            }
            Aluno aluno = usuario.getAluno();
            if (aluno != null) {
                aluno = em.getReference(aluno.getClass(), aluno.getAlunoId());
                usuario.setAluno(aluno);
            }
            em.persist(usuario);
            if (professor != null) {
                Usuario oldUsuarioOfProfessor = professor.getUsuario();
                if (oldUsuarioOfProfessor != null) {
                    oldUsuarioOfProfessor.setProfessor(null);
                    oldUsuarioOfProfessor = em.merge(oldUsuarioOfProfessor);
                }
                professor.setUsuario(usuario);
                professor = em.merge(professor);
            }
            if (administrador != null) {
                Usuario oldUsuarioOfAdministrador = administrador.getUsuario();
                if (oldUsuarioOfAdministrador != null) {
                    oldUsuarioOfAdministrador.setAdministrador(null);
                    oldUsuarioOfAdministrador = em.merge(oldUsuarioOfAdministrador);
                }
                administrador.setUsuario(usuario);
                administrador = em.merge(administrador);
            }
            if (status != null) {
                status.getUsuarioList().add(usuario);
                status = em.merge(status);
            }
            if (papel != null) {
                papel.getUsuarioList().add(usuario);
                papel = em.merge(papel);
            }
            if (avaliador != null) {
                Usuario oldUsuarioOfAvaliador = avaliador.getUsuario();
                if (oldUsuarioOfAvaliador != null) {
                    oldUsuarioOfAvaliador.setAvaliador(null);
                    oldUsuarioOfAvaliador = em.merge(oldUsuarioOfAvaliador);
                }
                avaliador.setUsuario(usuario);
                avaliador = em.merge(avaliador);
            }
            if (aluno != null) {
                Usuario oldUsuarioOfAluno = aluno.getUsuario();
                if (oldUsuarioOfAluno != null) {
                    oldUsuarioOfAluno.setAluno(null);
                    oldUsuarioOfAluno = em.merge(oldUsuarioOfAluno);
                }
                aluno.setUsuario(usuario);
                aluno = em.merge(aluno);
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findUsuario(usuario.getUserId()) != null) {
                throw new PreexistingEntityException("Usuario " + usuario + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Usuario usuario) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Usuario persistentUsuario = em.find(Usuario.class, usuario.getUserId());
            Professor professorOld = persistentUsuario.getProfessor();
            Professor professorNew = usuario.getProfessor();
            Administrador administradorOld = persistentUsuario.getAdministrador();
            Administrador administradorNew = usuario.getAdministrador();
            Status statusOld = persistentUsuario.getStatus();
            Status statusNew = usuario.getStatus();
            Papeis papelOld = persistentUsuario.getPapel();
            Papeis papelNew = usuario.getPapel();
            Avaliador avaliadorOld = persistentUsuario.getAvaliador();
            Avaliador avaliadorNew = usuario.getAvaliador();
            Aluno alunoOld = persistentUsuario.getAluno();
            Aluno alunoNew = usuario.getAluno();
            List<String> illegalOrphanMessages = null;
            if (professorOld != null && !professorOld.equals(professorNew)) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("You must retain Professor " + professorOld + " since its usuario field is not nullable.");
            }
            if (administradorOld != null && !administradorOld.equals(administradorNew)) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("You must retain Administrador " + administradorOld + " since its usuario field is not nullable.");
            }
            if (avaliadorOld != null && !avaliadorOld.equals(avaliadorNew)) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("You must retain Avaliador " + avaliadorOld + " since its usuario field is not nullable.");
            }
            if (alunoOld != null && !alunoOld.equals(alunoNew)) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("You must retain Aluno " + alunoOld + " since its usuario field is not nullable.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (professorNew != null) {
                professorNew = em.getReference(professorNew.getClass(), professorNew.getProfessorId());
                usuario.setProfessor(professorNew);
            }
            if (administradorNew != null) {
                administradorNew = em.getReference(administradorNew.getClass(), administradorNew.getAdminId());
                usuario.setAdministrador(administradorNew);
            }
            if (statusNew != null) {
                statusNew = em.getReference(statusNew.getClass(), statusNew.getTipo());
                usuario.setStatus(statusNew);
            }
            if (papelNew != null) {
                papelNew = em.getReference(papelNew.getClass(), papelNew.getTipo());
                usuario.setPapel(papelNew);
            }
            if (avaliadorNew != null) {
                avaliadorNew = em.getReference(avaliadorNew.getClass(), avaliadorNew.getAvaliadorId());
                usuario.setAvaliador(avaliadorNew);
            }
            if (alunoNew != null) {
                alunoNew = em.getReference(alunoNew.getClass(), alunoNew.getAlunoId());
                usuario.setAluno(alunoNew);
            }
            usuario = em.merge(usuario);
            if (professorNew != null && !professorNew.equals(professorOld)) {
                Usuario oldUsuarioOfProfessor = professorNew.getUsuario();
                if (oldUsuarioOfProfessor != null) {
                    oldUsuarioOfProfessor.setProfessor(null);
                    oldUsuarioOfProfessor = em.merge(oldUsuarioOfProfessor);
                }
                professorNew.setUsuario(usuario);
                professorNew = em.merge(professorNew);
            }
            if (administradorNew != null && !administradorNew.equals(administradorOld)) {
                Usuario oldUsuarioOfAdministrador = administradorNew.getUsuario();
                if (oldUsuarioOfAdministrador != null) {
                    oldUsuarioOfAdministrador.setAdministrador(null);
                    oldUsuarioOfAdministrador = em.merge(oldUsuarioOfAdministrador);
                }
                administradorNew.setUsuario(usuario);
                administradorNew = em.merge(administradorNew);
            }
            if (statusOld != null && !statusOld.equals(statusNew)) {
                statusOld.getUsuarioList().remove(usuario);
                statusOld = em.merge(statusOld);
            }
            if (statusNew != null && !statusNew.equals(statusOld)) {
                statusNew.getUsuarioList().add(usuario);
                statusNew = em.merge(statusNew);
            }
            if (papelOld != null && !papelOld.equals(papelNew)) {
                papelOld.getUsuarioList().remove(usuario);
                papelOld = em.merge(papelOld);
            }
            if (papelNew != null && !papelNew.equals(papelOld)) {
                papelNew.getUsuarioList().add(usuario);
                papelNew = em.merge(papelNew);
            }
            if (avaliadorNew != null && !avaliadorNew.equals(avaliadorOld)) {
                Usuario oldUsuarioOfAvaliador = avaliadorNew.getUsuario();
                if (oldUsuarioOfAvaliador != null) {
                    oldUsuarioOfAvaliador.setAvaliador(null);
                    oldUsuarioOfAvaliador = em.merge(oldUsuarioOfAvaliador);
                }
                avaliadorNew.setUsuario(usuario);
                avaliadorNew = em.merge(avaliadorNew);
            }
            if (alunoNew != null && !alunoNew.equals(alunoOld)) {
                Usuario oldUsuarioOfAluno = alunoNew.getUsuario();
                if (oldUsuarioOfAluno != null) {
                    oldUsuarioOfAluno.setAluno(null);
                    oldUsuarioOfAluno = em.merge(oldUsuarioOfAluno);
                }
                alunoNew.setUsuario(usuario);
                alunoNew = em.merge(alunoNew);
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = usuario.getUserId();
                if (findUsuario(id) == null) {
                    throw new NonexistentEntityException("The usuario with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Usuario usuario;
            try {
                usuario = em.getReference(Usuario.class, id);
                usuario.getUserId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The usuario with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            Professor professorOrphanCheck = usuario.getProfessor();
            if (professorOrphanCheck != null) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Usuario (" + usuario + ") cannot be destroyed since the Professor " + professorOrphanCheck + " in its professor field has a non-nullable usuario field.");
            }
            Administrador administradorOrphanCheck = usuario.getAdministrador();
            if (administradorOrphanCheck != null) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Usuario (" + usuario + ") cannot be destroyed since the Administrador " + administradorOrphanCheck + " in its administrador field has a non-nullable usuario field.");
            }
            Avaliador avaliadorOrphanCheck = usuario.getAvaliador();
            if (avaliadorOrphanCheck != null) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Usuario (" + usuario + ") cannot be destroyed since the Avaliador " + avaliadorOrphanCheck + " in its avaliador field has a non-nullable usuario field.");
            }
            Aluno alunoOrphanCheck = usuario.getAluno();
            if (alunoOrphanCheck != null) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Usuario (" + usuario + ") cannot be destroyed since the Aluno " + alunoOrphanCheck + " in its aluno field has a non-nullable usuario field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Status status = usuario.getStatus();
            if (status != null) {
                status.getUsuarioList().remove(usuario);
                status = em.merge(status);
            }
            Papeis papel = usuario.getPapel();
            if (papel != null) {
                papel.getUsuarioList().remove(usuario);
                papel = em.merge(papel);
            }
            em.remove(usuario);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Usuario> findUsuarioEntities() {
        return findUsuarioEntities(true, -1, -1);
    }

    public List<Usuario> findUsuarioEntities(int maxResults, int firstResult) {
        return findUsuarioEntities(false, maxResults, firstResult);
    }

    private List<Usuario> findUsuarioEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Usuario.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Usuario findUsuario(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Usuario.class, id);
        } finally {
            em.close();
        }
    }

    public int getUsuarioCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Usuario> rt = cq.from(Usuario.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
